﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Seven.Member.Internal;

namespace Seven.Member
{
    /// <summary>
    /// 定义一组用于用户身份校验、登录和密码服务的 API。
    /// </summary>
    public class MemberClient
    {
        #region 内部属性定义 - 获取在线用户信息

        /// <summary>
        /// 获取用于存储在线用户列表信息的集合。
        /// </summary>
        internal static MemberTokenCollection Tokens
        {
            get { return MemberToken.Tokens; }
        }

        #endregion

        #region 公共属性定义 - 获取在线用户信息

        /// <summary>
        /// 获取当前在线的所有登录身份信息列表。
        /// <para>注意该属性每次进行 get 读取操作时都会生成一个新的数组，所以如果要在一个会话/方法中多次读取该结果集，建议在一次获取该属性值后用变量缓存起来供多次调用。</para>
        /// </summary>
        public static MemberToken[] OnlineTokens
        {
            get { return Tokens.GetOnlineTokens().ToArray(); }
        }

        /// <summary>
        /// 获取当前在线的所有登录用户的总数量。
        /// <para>该属性每次进行 get 操作时都会对在线用户列表进行一次数量统计，所以如果要在一个会话/方法中多次读取该属性值，建议在一次获取该属性值后用变量缓存起来供多次调用。</para>
        /// </summary>
        public static int OnlineTokensCount
        {
            get { return OnlineTokens.Length; }
        }

        #endregion

        #region 公共方法定义 - 登录和注销登录

        /// <summary>
        /// 身份验证登录服务的核心 API 之一；以指定的登录帐号（用户名或登录别名）和密码进行系统登录操作。
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="password">密码明文</param>
        /// <param name="resultModel">输出参数，用户数据模型</param>
        /// <returns></returns>
        public static LoginResult Login(string account, string password, out UserInfoModel resultModel)
        {
            return MemberToken.UserLogin(account, password, out resultModel);
        }

        /// <summary>
        /// 身份验证登录服务的核心 API 之一；以指定的移动设备硬件编号、登录帐号（用户名或登录别名）和密码进行移动设备登录操作。
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="password">密码明文</param>
        /// <param name="resultModel">输出参数，用户数据模型</param>
        /// <returns></returns>
        public static LoginResult Login(string imei, string account, string password, out UserInfoModel resultModel)
        {
            return MemberToken.UserLogin(imei, account, password, out resultModel);
        }


        /// <summary>
        /// 以指定的登录帐号（用户名或登录别名）和密码进行系统强制登录操作。
        /// <para>强制登录将导致 <paramref name="account"/> 当前在其他设备的登录强制下线。</para>
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="password">密码明文</param>
        /// <param name="resultModel">输出参数，用户数据模型</param>
        /// <returns></returns>
        public static bool ForcedLogin(string account, string password, out UserInfoModel resultModel)
        {
            return MemberToken.UserForcedLogin(account, password, out resultModel);
        }

        /// <summary>
        /// 身份验证登录服务的核心 API 之一；以指定的移动设备硬件编号、登录帐号（用户名或登录别名）和密码进行移动设备强制登录操作。
        /// <para>强制登录将导致 <paramref name="imei"/> 参数所示移动设备及当前登录该设备的用户、或者 <paramref name="account"/> 参数所示用户当前在其他设备的登录强制下线。</para>
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="password">密码明文</param>
        /// <param name="resultModel">输出参数，用户数据模型</param>
        /// <returns></returns>
        public static bool ForcedLogin(string imei, string account, string password, out UserInfoModel resultModel)
        {
            return MemberToken.UserForcedLogin(imei, account, password, out resultModel);
        }


        /// <summary>
        /// 身份验证登录服务的核心 API 之一；对指定的登录帐号（用户名或登录别名）执行注销登录操作。
        /// <para>该登录帐号（用户名或登录别名）在所有设备上的登录状态将会改变为离线。</para>
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）。</param>
        /// <returns></returns>
        public static IEnumerable<KeyValuePair<Guid, LogoutResult>> Logout(string account)
        {
            return MemberToken.UserLogout(account);
        }

        /// <summary>
        /// 身份验证登录服务的核心 API 之一；对指定的登录身份的票据执行注销登录操作。
        /// <para>该登录身份票据值和所对应用户的登录状态将会改变为离线。</para>
        /// </summary>
        /// <param name="tokenGuid">登录身份的票据值。</param>
        /// <returns></returns>
        public static LogoutResult Logout(Guid tokenGuid)
        {
            return MemberToken.UserLogout(tokenGuid);
        }


        /// <summary>
        /// 身份验证登录服务的核心 API 之一；按移动设备硬件编号指定移动设备执行注销登录操作。
        /// <para>该移动设备的登录状态及 设备上登录的用户将同时改变为离线。</para>
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <returns></returns>
        public static LogoutResult PhoneLogout(string imei)
        {
            return MemberToken.PhoneLogout(imei);
        }

        #endregion


        #region 公共方法定义 - 登录状态验证

        /// <summary>
        /// 验证 <paramref name="tokenKey"/> 指定的登录身份是否有效且在线，并且登录用户为 <paramref name="account"/>。
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="tokenKey">登录身份的Token标识</param>
        /// <returns></returns>
        public static bool ValidateUserTokenLoginState(string account, Guid tokenKey)
        {
            return MemberToken.ValidateUserTokenLoginState(account, tokenKey);
        }

        /// <summary>
        /// 验证 <paramref name="tokenKey"/> 指定的登录身份是否有效且在线，并且为移动设备登录同时设备编号为 <paramref name="imei"/>。
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <param name="tokenKey">登录身份的Token标识</param>
        /// <returns></returns>
        public static bool ValidatePhoneTokenLoginState(string imei, Guid tokenKey)
        {
            return MemberToken.ValidatePhoneTokenLoginState(imei, tokenKey);
        }


        /// <summary>
        /// 验证 <paramref name="tokenKey"/> 指定的登录身份是否有效且在线，并且登录用户为 <paramref name="account"/> 同时为移动设备登录同时移动设备登录设备编号为 <paramref name="imei"/>。
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="imei">移动设备硬件编号</param>
        /// <param name="tokenKey">登录身份的Token标识</param>
        /// <returns></returns>
        public static bool ValidateUserPhoneTokenLoginState(string account, string imei, Guid tokenKey)
        {
            return MemberToken.ValidateUserPhoneTokenLoginState(account, imei, tokenKey);
        }

        #endregion


        #region 公共方法定义 - 用户身份和密码验证

        /// <summary>
        /// 验证指定的用户密码是否匹配当前用户。
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <param name="password">密码明文</param>
        /// <returns></returns>
        public static bool ValidatePassword(string account, string password)
        {
            return MemberToken.ValidatePassword(account, password);
        }

        #endregion


        #region 公共方法定义 - 刷新登录状态
        
        /// <summary>
        /// 刷新用户身份标识的最后一次提交请求到服务器的时间。
        /// </summary>
        /// <param name="tokenGuid">用户身份标识</param>
        /// <returns></returns>
        public static bool UpdateTokenLastRequestTime(Guid tokenGuid)
        {
            MemberToken token = GetTokenByGuid(tokenGuid);
            if (token != null)
            {
                token.UpdateLastRequestTime();
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 刷新移动设备身份标识的最后一次提交请求到服务器的时间。
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <returns></returns>
        public static bool UpdateTokenLastRequestTimeByIMEI(string imei)
        {
            MemberToken token = GetTokenByIMEI(imei);
            if (token != null)
            {
                token.UpdateLastRequestTime();
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion


        #region 公共方法定义 - 获取登录状态相关信息

        /// <summary>
        /// 根据指定的移动设备编号获取当前登录该设备的用户身份信息。
        /// <para>如果该方法返回 null，则说明该移动设备编号无效或者当前时间没有用户使用该编号的移动设备登录。</para>
        /// </summary>
        /// <param name="imei"></param>
        /// <returns></returns>
        public static MemberToken GetTokenByIMEI(string imei)
        {
            return MemberToken.GetTokenByIMEI(imei);
        }

        /// <summary>
        /// 根据指定的登录帐号（用户名或登录别名）获取该用户的登录身份信息。
        /// <para>如果该方法返回 null，则说明该用户无效或者尚未登录。</para>
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <returns></returns>
        public static MemberToken[] GetTokenByAccount(string account)
        {
            return MemberToken.GetTokenByAccount(account);
        }

        /// <summary>
        /// 根据指定的登录身份信息的 Token KEY 值获取该登陆身份信息。
        /// <para>如果该方法返回 null，则说明该 <paramref name="token"/> 无效。</para>
        /// </summary>
        /// <param name="token">登录身份信息的 Token KEY 值</param>
        /// <returns></returns>
        public static MemberToken GetTokenByGuid(Guid token)
        {
            return MemberToken.GetTokenByGuid(token);
        }


        /// <summary>
        /// 判断指定的登录帐号（用户名或登录别名）是否当前登录在线。
        /// </summary>
        /// <param name="account">登录帐号（用户名或登录别名）</param>
        /// <returns></returns>
        public static bool IsOnline(string account)
        {
            return MemberToken.IsOnline(account);
        }

        /// <summary>
        /// 根据指定的登录身份 KEY 值信息判断该登录身份是否当前登录在线。
        /// </summary>
        /// <param name="token">登录身份 KEY 值</param>
        /// <returns></returns>
        public static bool IsOnline(Guid token)
        {
            return MemberToken.IsOnline(token);
        }

        /// <summary>
        /// 根据移动设备的编号判断指定的移动设备是否当前登录在线。
        /// </summary>
        /// <param name="imei">移动设备硬件编号</param>
        /// <returns></returns>
        public static bool PhoneIsOnline(string imei)
        {
            return MemberToken.PhoneIsOnline(imei);
        }

        #endregion

        #region 公共方法定义 - 清空用户池

        /// <summary>
        /// 清空用户池
        /// </summary>
        public static void ClearMemberPool()
        {
            MemberToken.Tokens.Clear();
        }

        #endregion
    }
}
